import json
from datetime import datetime
from django.http import JsonResponse, HttpResponse
from django.views import View
from .models import BookInfo, HeroInfo

"""

# 书籍信息
GET         /api/books/
POST        /api/books/
GET         /api/books/<pk>/
PUT         /api/books/<pk>/
DELETE      /api/books/<pk>/

# 人物信息
GET         /api/heros/
POST        /api/heros/
GET         /api/heros/<pk>/
PUT         /api/heros/<pk>/
DELETE      /api/heros/<pk>/


响应数据  JSON
# 列表视图: 路由后边没有 pk/ID
# 详情视图: 路由后面   pk/ID
"""


class BooksAPIVIew(View):
    """
    查询所有图书、增加图书
    """

    def get(self, request):
        """
        查询所有图书
        路由：GET /api/books/
        """
        # 1. 查询出所有图书模型
        queryset = BookInfo.objects.all()
        # 2. 遍历查询集，去除里边的每个书籍模型对象，把模型对象转换成字典
        # 定义一个列表保存所有字典
        book_list = []
        for book in queryset:
            book_dict = {
                'id': book.id,
                'btitle': book.btitle,
                'bput_date': book.bpub_date,
                'bread': book.bcomment,
                'image': book.image.url if book.image else '',
            }
            book_list.append(book_dict)  # 将转换好的字典添加到列表中
        # 3. 响应给前端
        # 如果book_list 不是一个字典的话就需要将safe设置成False.
        return JsonResponse(book_list, safe=False)

    def post(self, request):
        """
        新增图书
        路由：POST /api/books/
        """
        # 获取前端传入的请求体数据(json) request.body
        json_bytes = request.body
        # 把bytes类型的json字符串转换成json_str
        json_str = json_bytes.decode()
        # 利用json.loads将json字符串转换为json（字典/列表）
        book_dict = json.loads(json_str)

        # 此处详细的校验参数省略
        # 创建模型对象并保存（把字典转换成模型并储存）
        book = BookInfo(
            btitle=book_dict['btitle'],
            bpub_date=book_dict['bpub_date'],

        )
        book.save()

        # 把新增的模型转换成字典
        json_dict = {
            'id': book.id,
            'btitle': book.btitle,
            'bput_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'image': book.image.url if book.image else '',
        }
        # 响应（把新增的数据再响应回去，201）
        return JsonResponse(json_dict, status=201)


class BookAPIView(View):
    """详情视图"""

    def get(self, request, pk):
        """
        获取单个图书信息
        路由： GET  /api/books/<pk>/
        """
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '查询的数据不存在'}, status=404)
        # 2. 模型对象转字典
        book_dict = {
            'id': book.id,
            'btitle': book.btitle,
            'bput_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'image': book.image.url if book.image else '',
        }
        # 3. 响应
        return JsonResponse(book_dict)

    def put(self, request, pk):
        """
        修改图书信息
        路由： PUT  /api/books/<pk>
        """
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '修改的数据不存在'}, status=404)

        # 获取前端传入的新数据（把数据转换成字典）
        # json_str_bytes = request.body
        # json_str = json_str_bytes.decode()
        # book_dict = json.loads(json_str)

        # 此处详细的校验参数省略
        book_dict = json.loads(request.body.decode())
        # 重新给模型指定的属性赋值
        book.btitle = book_dict['btitle']
        book.bpub_date = book_dict['bpub_date']
        # 调用save方法进行修改操作
        book.save()
        # 把修改后的模型再转换成字典
        json_dict = {
            'id': book.id,
            'btitle': book.btitle,
            'bput_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'image': book.image.url if book.image else '',
        }
        # 响应
        return JsonResponse(json_dict)

    def delete(self, request, pk):
        """
        删除图书
        路由： DELETE /api/books/<pk>/
        """
        # 获取要删除的模型对象
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '删除的数据不存在'}, status=404)
        # 删除指定模型对象
        # book.delete()  # 物理删除（真正从数据库删除）
        book.is_delete = True
        book.save()  # （逻辑删除）
        # 响应：删除时不需要有响应体但要指定状态码为 204
        return HttpResponse(status=204)


class HerosAPIVIew(View):
    """
    查询所有人物信息，新增人物
    """

    def get(self, request):
        """
        查询所有人物
        路由：GET /api/heros/
        """
        queryset = HeroInfo.objects.all()
        heros_list = []
        for hero in queryset:
            book_dict = {
                'id': hero.id,
                'hname': hero.hname,
                'hgender': hero.hgender,
                'hcomment': hero.hcomment,
                "hbookid": hero.hbook.id,
                "hbookBtitle": hero.hbook.btitle,
                "hbookBread": hero.hbook.bread
            }
            heros_list.append(book_dict)
        return JsonResponse(heros_list, safe=False)

    def post(self, request):
        """
        新增人物
        路由：POST /api/heros/
        """
        json_bytes = request.body
        json_str = json_bytes.decode()
        heros_dict = json.loads(json_str)

        # 获取关联的图书对象
        book_id = heros_dict['hbook']
        book = BookInfo.objects.get(id=book_id)

        # 创建英雄对象并保存到数据库
        hero = HeroInfo(
            hname=heros_dict['hname'],
            hgender=heros_dict['hgender'],
            hcomment=heros_dict['hcomment'],
            hbook=book,  # 将关联的图书对象赋值给外键属性
        )
        hero.save()
        json_dict = {
            'id': hero.id,
            'hname': hero.hname,
            'hgender': hero.hgender,
            'hcomment': hero.hcomment,
            'hbook': hero.hbook.btitle
        }
        return JsonResponse(json_dict, status=201)


class HeroAPIView(View):
    """详情视图"""

    def get(self, request, pk):
        """
        获取单个人物信息
        路由： GET  /api/heros/<pk>/
        """
        try:
            hero = HeroInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '查询的数据不存在'}, status=404)
        book_dict = {
            'id': hero.id,
            'hname': hero.hname,
            'hgender': hero.hgender,
            'hcomment': hero.hcomment,
            "hbookid": hero.hbook.id,
            "hbookBtitle": hero.hbook.btitle,
            "hbookBread": hero.hbook.bread
        }
        return JsonResponse(book_dict)

    def put(self, request, pk):
        """
        更新人物信息
        路由： PUT  /api/heros/<pk>
        """
        json_bytes = request.body
        json_str = json_bytes.decode()
        heros_dict = json.loads(json_str)

        try:
            # 获取需要更新的英雄对象
            hero = HeroInfo.objects.get(id=pk)
        except HeroInfo.DoesNotExist:
            return JsonResponse({'message': '修改的数据不存在'}, status=404)

        # 更新英雄信息
        hero.hname = heros_dict['hname']
        hero.hgender = heros_dict['hgender']
        hero.hcomment = heros_dict['hcomment']

        # 获取关联的图书对象
        book_id = heros_dict['hbook']
        book = BookInfo.objects.get(id=book_id)
        # 更新外键关联属性
        hero.hbook = book
        # 保存更新后的英雄对象
        hero.save()

        # 构造响应数据并返回
        json_dict = {
            'id': hero.id,
            'hname': hero.hname,
            'hgender': hero.hgender,
            'hcomment': hero.hcomment,
            'hbook': hero.hbook.btitle  # 将外键关联对象的名称进行序列化
        }
        return JsonResponse(json_dict, status=200)

    def delete(self, request, pk):
        """
        删除人物
        路由： DELETE /api/heros/<pk>/
        """
        try:
            hero = HeroInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '删除的数据不存在'}, status=404)
        # hero.delete()  # 物理删除（真正从数据库删除）
        hero.is_delete = True
        hero.save()  # （逻辑删除）
        # 响应：删除时不需要有响应体但要指定状态码为 204
        return HttpResponse(status=204)
